<?php
/**
 * EventRepo.php
 *
 * @copyright   2023 thingsworld.com.cn - All Rights Reserved
 * @link        http://thingsworld.com.cn/
 * @author      stiffer.chen <chenl@thingsworld.com.cn>
 * @created     2023-02-20 19:20:45
 * @modified    2023-02-20 19:20:45
 *
 */

namespace App\Repositories;

use App\Library\Logger;
use App\Models\CityModel;
use App\Models\Customer;
use App\Models\Event;
use App\Models\UserModel;
use App\Services\DeptService;
use App\Services\SmsService;
use App\Services\WsService;
use Carbon\Carbon;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class EventRepo
{
    const TYPE_REQUEST = '服务请求';
    const TYPE_REPAIR = '客户报修';
    const TYPE_ORDER = '服务订单';
    const TYPE_MAINTENANCE = '维保服务';
    const TYPE_MANAGE = '项目管理';
    const TYPE_COMPLAIN = '投诉建议';

    const STATUS_ALL = '全部';
    const STATUS_UN_DISTRIBUTE = '待分配';
    const STATUS_UN_PROCESS = '已分配';
    const STATUS_PROCESSING = '处理中';
    const STATUS_COMPLETE = '已完成';
    const STATUS_CLOSED = '已关闭'; // 转工单

    const CREATED_CUSTOMER = '客户自助';
    const CREATED_USER = '客服录入';

    // sprintf($str, "NUM123456")

    /**
     * 事件提交 app通知
     * 触发点: 事件提交时
     * 接收对象: 区域负责人
     */
    const NOTIFY_SUBMIT = [
        'title' => '事件新增',
        'content' => "您有一个新的事件需要处理，编号: %s"
    ];

    /**
     * 事件提交 sms通知
     * 触发点: 事件提交时
     * 接收对象: 客户
     */
    const SMS_SUBMIT = [
        'sms_code' => 'SMS_463610396',
        'variables' => []
    ];

    /**
     * 事件分配
     * 触发点: 事件分配时
     * 接收对象: 事件负责人 + 创建人
     */
    const NOTIFY_ALLOT = [
        'title' => '事件新增',
        'content' => "您有一个新的事件需要处理，编号: %s"
    ];

    /**
     * 事件分配 sms通知
     * 触发点: 事件分配时
     * 接收对象: 客户
     */
    const SMS_ALLOT = [
        'sms_code' => 'SMS_463680418',
        'variables' => []
    ];

    /**
     * 事件完成
     * 触发点: 事件完成时
     * 接收对象: 创建人+区域主管
     */
    const NOTIFY_COMPLETE = [
        'title' => '事件完成',
        'content' => "事件: %s 已完成，请您查看"
    ];

    /**
     * 事件完成 sms通知
     * 触发点: 事件完成时
     * 接收对象: 客户
     * 参数:
     *      user: 工程师姓名
     *      phone: 工程师电话
     */
    const SMS_COMPLETE = [
        'sms_code' => 'SMS_274545078',
        'variables' => [
            'user',
            'phone'
        ]
    ];

    /**
     * 事件转工单
     * 触发点: 事件转工单时
     * 接收对象: 创建人+区域主管+工单负责人
     */
    const NOTIFY_CONV = [
        'title' => '事件转工单',
        'content' => "事件: %s 已经转工单处理"
    ];

    /**
     * 事件转工单 sms通知
     * 触发点: 事件转工单
     * 接收对象: 客户
     * 参数:
     *      event_id: 事件编号
     *      customer_telephone: 客服电话
     */
    const SMS_CONV = [
        'sms_code' => 'SMS_463655437',
        'variables' => [
            'event_id',
            'customer_telephone'
        ]
    ];

    // 新事件通知
    const SMS_NOTIFY_NEW = [
        'sms_code' => 'SMS_463630415',
        'variables' => [
            'event_number'
        ]
    ];

    /**
     * 待分配 => 待处理(已分配)|已关闭
     * 待处理 => 处理中
     * 处理中 => 已完成
     */
    public static function machine()
    {
        return [
            self::STATUS_UN_DISTRIBUTE => [
                self::STATUS_UN_PROCESS,
                self::STATUS_CLOSED
            ],
            self::STATUS_UN_PROCESS => [
                self::STATUS_PROCESSING
            ],
            self::STATUS_PROCESSING => [
                self::STATUS_COMPLETE
            ],
            self::STATUS_CLOSED
        ];
    }

    public static function correlation($id)
    {
        $event = Event::find($id);
        if (empty($event)) {
            throw new \Exception('事件不存在');
        }
        $data = request()->getContent();
        $arr = json_decode($data, true);
        $customerId = $arr['customer_id'] ?? 0;
        $customerUserId = $arr['customer_user_id'] ?? 0;
        $customer = Customer::find($customerId);
        if (empty($customer)) {
            throw new \Exception('客户不存在');
        }
        $customerUser = Customer\User::find($customerUserId);
        if (empty($customerUser)) {
            throw new \Exception('客户联系人不存在');
        }
        if ($customerUser->customer_id != $customer->id) {
            throw new \Exception('客户联系人不属于该客户');
        }
        $event->customer_id = $customer->id;
        $event->customer_user_id = $customerUser->id;
        $event->saveOrFail();
    }

    public static function status()
    {
        // reason: http://pm.thingsworld.com.cn/index.php?m=bug&f=view&bugID=70
        return [
            // self::STATUS_ALL,
            self::STATUS_UN_DISTRIBUTE,
            self::STATUS_UN_PROCESS,
            // self::STATUS_PROCESSING,
            self::STATUS_COMPLETE,
            self::STATUS_CLOSED
        ];
    }

    public static function params()
    {
        return [
            'types' => [
                // self::TYPE_REQUEST,
                self::TYPE_REPAIR,
                // self::TYPE_MAINTENANCE,
                // self::TYPE_MANAGE,
                self::TYPE_COMPLAIN
            ],
            'statuses' => self::status()
        ];
    }

    public static function getList()
    {
        $perPage = (int)request('limit');
        if ($perPage < 1) {
            $perPage = 1;
        }
        $builder = Event::query()->select(['event.*']);
        $builder->with(['product', 'images']);
        $status = trim(\request()->get('status') ?? '');
        if ($status) {
            $builder->where('event.status', '=', $status);
        }
        $aboutMe = trim(\request()->get('about_me') ?? '');
        $date = trim(\request()->get('date') ?? '');
        $userId = registry('user_id');
        if ($aboutMe == 'assist') {
            $builder->join('event_user', 'event_user.event_id', '=', 'event.id')
                ->where('event_user.user_id', '=', $userId)
                ->where('event_user.is_master', '=', 0);
        }
        if ($aboutMe == 'master') {
            $builder->join('event_user', 'event_user.event_id', '=', 'event.id')
                ->where('event_user.user_id', '=', $userId)
                ->where('event_user.is_master', '=', 1);
        }
        if ($aboutMe == 'create') {
            $builder->where('event.created_type',self::CREATED_USER)
                ->where('event.created_by', $userId);
        }

        $customerName = trim(request('customer_name', ''));
        $contactName = trim(request('contact_name', ''));
        $contactPhone = trim(request('contact_phone', ''));

        if ($customerName) {
            $builder->join('customer', 'customer.id', '=', 'event.customer_id')
                ->where('customer.name', 'like', "%{$customerName}%");
        }

        if ($contactName) {
            $builder->where('event.contact_name', 'like', "%{$customerName}%");
        }

        if ($contactPhone) {
            $builder->where('event.contact_telephone', 'like', "%{$contactPhone}%");
        }

        $type = trim(\request()->get('type') ?? '');
        if ($type) {
            $builder->where('event.type', $type);
        }

        $dateStart = $dateEnd = 0;
        if ($date == 'today') {
            $dateNow = Carbon::now()->toDateString();
            $start = $dateNow . ' 00:00:00';
            $end = $dateNow . ' 23:59:59';
            $dateStart = strtotime($start);
            $dateEnd = strtotime($end);
        }

        if ($date == 'week') {
            $dateFirst = Carbon::now()->startOfWeek()->toDateString();
            $dateNow = Carbon::now()->toDateString();
            $start = $dateFirst . ' 00:00:00';
            $end = $dateNow . ' 23:59:59';
            $dateStart = strtotime($start);
            $dateEnd = strtotime($end);
        }

        if ($date == 'month') {
            $dateFirst = Carbon::now()->startOfMonth()->toDateString();
            $dateNow = Carbon::now()->toDateString();
            $start = $dateFirst . ' 00:00:00';
            $end = $dateNow . ' 23:59:59';
            $dateStart = strtotime($start);
            $dateEnd = strtotime($end);
        }

        if ($date == 'year') {
            $dateFirst = Carbon::now()->startOfYear()->toDateString();
            $dateNow = Carbon::now()->toDateString();
            $start = $dateFirst . ' 00:00:00';
            $end = $dateNow . ' 23:59:59';
            $dateStart = strtotime($start);
            $dateEnd = strtotime($end);
        }

        if ($dateStart) {
            $builder->where('event.create_time', '>=', $dateStart);
        }
        if ($dateEnd) {
            $builder->where('event.create_time', '<=', $dateEnd);
        }

        $number = trim(request()->get('number') ?? '');
        if ($number) {
            $builder->where('event.event_number', 'like', "%{$number}%");
        }

        $currentUser = registry('user');
        $currentUserId = registry('user_id');

        $currentUserDeptId = $currentUser->dept_id;
        $deptService = new DeptService();
        // 所有能看的省份
        $allProvinceIds = $deptService->getAllProvinceIds($currentUserDeptId);
        if ($currentUserId != 1) {
            // $builder->whereIn('event.province_id', $allProvinceIds);
        }
        $builder->leftJoin('event_user as eu', 'eu.event_id', '=', 'event.id');
        if ($currentUserId != 1) {
            if (is_engineer($currentUserId)) {
                // 工程师: 分配给自己的
                $builder->join('event_user as eu', 'eu.event_id', '=', 'event.id')
                    ->where('eu.user_id', $currentUserId);
            } else {
                // 非工程师: 自己创建的 + 分配给自己的 + 当前省份的
                $builder->where(function ($query) use ($allProvinceIds, $currentUserId) {
                    $query->whereIn('event.province_id', $allProvinceIds)
                        ->orWhere(function ($subQuery) use ($currentUserId) {
                            $subQuery->where('created_type', EventRepo::CREATED_USER)
                                ->where('created_by', $currentUserId);
                        })
                        ->orWhere('eu.user_id', $currentUserId);
                });
            }
        }
        $builder->where('event.id', '<>', null);
        $builder->orderByDesc('event.update_time');
        $builder->distinct();

        $export = intval(request('export', ''));
        if ($export) {
            return self::exportData($builder);
        }

        return $builder->paginate($perPage);
    }

    private static function exportData($builder)
    {
        $idStr = trim(request('ids', ''));
        $idParam = [];
        if ($idStr) {
            $idArr = explode(',', $idStr);
            foreach ($idArr as $item) {
                $item = intval($item);
                if ($item > 0) {
                    $idParam[] = $item;
                }
            }
        }
        $builder->with(['work_order']);
        if ($idParam) {
            $builder->whereIn('event.id', $idParam);
        }
        $data = $builder->get()->toArray();
        return self::export($data);
    }

    private static function export($data)
    {
        $pathPrefix = 'downloads/event/' . date('Y/m/d/');
        $prefix = public_path() . '/' . $pathPrefix;
        $excelFileName = 'event-' . md5(date('YmdHis') . microtime()) . '.xlsx';

        if (!is_dir($prefix)) {
            mkdir($prefix, 0777, true);
        }
        $excelFilePath = $prefix . $excelFileName;
        $spreadsheet = new Spreadsheet();
        $sheet = new Worksheet($spreadsheet, "事件");
        $spreadsheet->addSheet($sheet);
        $spreadsheet->removeSheetByIndex(0);

        $excelData[] = [
            '序号',
            '事件编号',
            '事件类型',
            '工单编号',
            '客户',
            '联系人',
            '电话',
            '客户地址',
            '出厂编号',
            '状态',
            '创建方式',
            '创建时间'
        ];

        foreach ($data as $item) {
            $type = $item['type'];

            $typeText = $type;
            if ($type == \App\Repositories\Customer\EventRepo::TYPE_REPAIR) {
                $typeText = EventRepo::TYPE_REPAIR;
            } elseif ($type == \App\Repositories\Customer\EventRepo::TYPE_COMPLAIN) {
                $typeText = EventRepo::TYPE_COMPLAIN;
            }

            $customer = Customer::find($item['customer_id']);
            $excelData[] = [
                $item['id'],
                $item['event_number'],
                $typeText,
                $item['work_order']['wo_number'] ?? '',
                $item['customer_name'] ?: ($customer->name ?? ''),
                $item['contact_name'],
                ' ' . $item['contact_telephone'],
                $item['address'],
                ' ' . ($item['product']['product_number'] ?? ''),
                $item['status'],
                $item['created_type'],
                $item['create_time_format'],
            ];
        }

        $sheet->fromArray($excelData);
        $writer = new Xlsx($spreadsheet);
        $writer->save($excelFilePath);
        return env('APP_URL') . '/' . $pathPrefix . $excelFileName;
    }

    // 分配事件
    public static function allot($id)
    {
        $event = Event::find($id);
        if (empty($event)) {
            throw new \Exception('事件信息不存在');
        }
        if ($event->status != self::STATUS_UN_DISTRIBUTE) {
            throw new \Exception("仅". self::STATUS_UN_DISTRIBUTE . "的事件可以进行分配操作");
        }

        $eventData = request()->getContent();
        $eventArr = json_decode($eventData, true);

        $userId = intval($eventArr['user_id'] ?? 0);
        if (!$userId) {
            throw new \Exception("仅指定负责人");
        }
        $user = UserModel::find($userId);
        if (empty($user)) {
            throw new \Exception('负责人信息不存在');
        }

        // 通知事件负责人
        try {
            $smsTemplate = self::SMS_NOTIFY_NEW;
            $telephone = $user->mobile ?? '';
            $smsParams = ['event_number' => $event->event_number];
            $smsService = new SmsService($telephone);
            $smsService->sendMessage($smsTemplate['sms_code'], $smsParams);
        } catch (\Exception $e) {

        }

        $masterUserId = $userId;
        $masterUserName = $user->realname;


        $users = [];
        $users[] = [
            'user_id' => $userId,
            'is_master' => 1
        ];
        $assistUserIds = $eventArr['assist_user_ids'] ?? [];
        if ($assistUserIds) {
            foreach ($assistUserIds as $assistUserId) {
                $assistUserId = intval($assistUserId);
                if ($assistUserId <= 0) {
                    continue;
                }
                $users[] = [
                    'user_id' => $assistUserId,
                    'is_master' => 0
                ];
            }
        }

        $eventUsers = [];
        foreach ($users as $user) {
            $eventUsers[] = new Event\User($user);
        }

        $event->status = self::STATUS_UN_PROCESS;
        $event->saveOrFail();

        $event->users()->delete();
        $event->users()->saveMany($eventUsers);

        $eventHistory = new Event\StatusHistory(['status' => self::STATUS_UN_PROCESS]);
        $event->histories()->save($eventHistory);
        $creatorName = registry('user')->username ?? '';

        $pushUserIds[] = $masterUserId;
        // 推送 事件新增
        $createdBy = $event->created_by ?? '';
        $createdType = $event->created_type ?? '';
        if ($createdType == self::CREATED_USER) {
            $pushUserIds[] = $createdBy;
        }
        $pushUserIds = array_unique($pushUserIds);
        NotificationRepo::multiStore($pushUserIds, $event->id, NotificationRepo::TYPE_EVENT, self::NOTIFY_ALLOT['title'], sprintf(self::NOTIFY_ALLOT['content'], $event->event_number));

        $actionUser = registry('user');
        $actionUserName = $actionUser->realname ?? '';
        $status = $event->status ?? '';
        $eventNumber = $event->event_number;
        if ($status == self::STATUS_UN_PROCESS) {
            $logBody = [
                'creator' => $actionUserName,
                'action' => "把事件 {$eventNumber} 分配给了 {$masterUserName}"
            ];
            OperationLogRepo::createLog(OperationLogRepo::BUSINESS_TYPE_EVENT, $event->id, json_encode($logBody));
        }

        // ws notify
        self::wsSend($event->id, "事件已被分配, 编号: {$eventNumber}");

        self::sendSms($event->id, self::SMS_ALLOT);

        return self::fetch($id);
    }

    private static function wsSend($id, $message)
    {
        try {
            $wsType = WsService::TYPE_EVENT;
            (new WsService())->sendMessage($id, $wsType, $message);
        } catch (\Exception $e) {
            $log = new Logger('ws_service');
            $log->error($e->getMessage());
        }
    }

    // 开始处理
    public static function start($id)
    {
        $event = Event::find($id);
        if (empty($event)) {
            throw new \Exception('事件信息不存在');
        }
        if ($event->status != self::STATUS_UN_PROCESS) {
            throw new \Exception("仅". self::STATUS_UN_PROCESS . "的事件可以进行该操作");
        }
        // @todo 处理人判断

        $event->status = self::STATUS_PROCESSING;
        $event->saveOrFail();

        $eventHistory = new Event\StatusHistory(['status' => self::STATUS_PROCESSING]);
        $event->histories()->save($eventHistory);

        // 发送通知，记录 Log
        $number = $event->event_number;
        $action = "事件 #{$number} 状态变更为 " . self::STATUS_PROCESSING;
        $bodyData = [
            'creator' => registry('user')->username ?? '',
            'action' => $action
        ];
        OperationLogRepo::createLog(OperationLogRepo::BUSINESS_TYPE_EVENT, $event->id, json_encode($bodyData));
        self::wsSend($event->id, "工程师已开始处理工单 #{$number}");
        return self::fetch($id);
    }

    // 回执
    public static function receipt($id)
    {
        $event = Event::find($id);
        if (empty($event)) {
            throw new \Exception('事件信息不存在');
        }
        if ($event->status != self::STATUS_UN_PROCESS) {
            throw new \Exception("仅". self::STATUS_UN_PROCESS . "的事件可以进行回执操作");
        }

        $receiptData = request()->getContent();
        $receiptArr = json_decode($receiptData, true);

        $description = trim($receiptArr['description'] ?? '');
        $images = [];
        foreach ($receiptArr['images'] ?? [] as $item) {
            $images[] = new Event\Receipt\Image([
                'image' => $item
            ]);
        }

        $event->status = self::STATUS_COMPLETE;
        $event->saveOrFail();

        $receipt = new Event\Receipt();
        $receipt->fill([
            'event_id' => $event->id,
            'description' => $description
        ]);
        $receipt->saveOrFail();

        if ($images) {
            $receipt->images()->saveMany($images);
        }

        $eventHistory = new Event\StatusHistory(['status' => self::STATUS_COMPLETE]);
        $event->histories()->save($eventHistory);

        $createdType = $event->created_type;
        $createdBy = $event->created_by;
        $provinceId = $event->province_id ?? 0;
        $leaderIds = (new DeptService())->getLeaderIdsByProvinceId($provinceId);
        if ($leaderIds) {
            if ($createdType == self::CREATED_USER) {
                $leaderIds[] = $createdBy;
            }
            $leaderIds = array_unique($leaderIds);
            NotificationRepo::multiStore($leaderIds, $event->id, NotificationRepo::TYPE_EVENT, self::NOTIFY_COMPLETE['title'], sprintf(self::NOTIFY_COMPLETE['content'], $event->event_number));
        }
        $eventNumber = $event->event_number;
        self::wsSend($event->id, "事件已完成, 编号: {$eventNumber}");

        $actionUser = registry('user');
        $actionUserName = $actionUser->realname ?? '';
        $logBody = [
            'creator' => $actionUserName,
            'action' => "事件已完成 {$eventNumber}"
        ];
        OperationLogRepo::createLog(OperationLogRepo::BUSINESS_TYPE_EVENT, $event->id, json_encode($logBody));

        $event = Event::find(1);
        $smsSendParams = [];
        $evenUser = Event\User::query()
            ->select(['user.realname', 'user.mobile'])
            ->join('user', 'user.id', '=', 'event_user.user_id')
            ->where('event_user.event_id', $event->id)
            ->where('event_user.is_master', 1)
            ->first();
        $smsSendParams['user'] = $evenUser->realname ?? '';
        $smsSendParams['phone'] = $evenUser->mobile ?? '';
        self::sendSms($event->id, self::SMS_COMPLETE, ['user' => $evenUser->realname ?? '', 'phone' => $evenUser->mobile ?? '']);

        return self::fetch($id);
    }

    public static function fetch($id)
    {
        $event = Event::query();
        $event->where('id', $id);
        $event->with(['product', 'images', 'receipt.images', 'customer']);
        $currentUser = registry('user');
        $currentUserId = registry('user_id');
        $currentUserDeptId = $currentUser->dept_id ?? 0;
        $deptService = new DeptService();
        // 所有能看的省份
        $allProvinceIds = $deptService->getAllProvinceIds($currentUserDeptId);
        if ($currentUserId != 1) {
            // $event->whereIn('event.province_id', $allProvinceIds);
        }
        // @todo 只能看当前区域及子区域数据

        if (!$event->count()) {
            return [];
        }
        $result = $event->first();

        if (empty($result)) {
            return $result;
        }

        $user = UserModel::query()
            ->select(['user.id', 'user.realname'])
            ->join('event_user as eu', 'eu.user_id', '=', 'user.id')
            ->where('eu.event_id', $id)
            ->where('eu.is_master', 1)
            ->first();

        $result->master_user_id = $user->id ?? 0;
        $result->master_user_name = $user->realname ?? '';

        return $result;

//        $event = Event::with(['product', 'images', 'receipt.images', 'customer'])->find($id);
//        return $event;
    }


    /**
     * 存储事件
     * @param int $id
     * @param int $createdBy 创建人ID
     * @param string $createdType 创建人类型
     */
    public static function store(int $id, int $createdBy, string $createdType, $data = [])
    {
        $actionUser = registry('user');
        $actionUserName = $actionUser->realname ?? '';

        if (empty($data)) {
            $data = self::requestData($id, $createdBy, $createdType);
        }
        $main = $data['main'];
        $images = $data['images'];
        $users = $data['users'];

        if ($createdType == self::CREATED_USER) {
            $creatorName = UserModel::find($createdBy)->username ?? '';
            $creatorName = $creatorName . "(客服)";
        } else {
            $creatorName = Customer\User::find($createdBy)->name ?? '';
            $creatorName = $creatorName . "(客户)";
        }

        if ($id) {
            $event = Event::find($id);
        } else {
            $event = new Event();
        }
        if (empty($event)) {
            $event = new Event();
        }

        $event->fill($main);
        $event->saveOrFail();

        if ($images) {
            $eventImages = [];
            foreach ($images as $image) {
                $eventImages[] = new Event\Image($image);
            }
            $event->images()->saveMany($eventImages);
        }

        if ($users) {
            $eventUsers = [];
            foreach ($users as $user) {
                $eventUsers[] = new Event\User($user);
            }
            $event->users()->saveMany($eventUsers);
        }

        $status = $main['status'];
        if ($status == self::STATUS_UN_PROCESS) {
            $eventHistory = new Event\StatusHistory(['status' => self::STATUS_UN_DISTRIBUTE]);
            $event->histories()->save($eventHistory);
        }
        $eventHistory = new Event\StatusHistory(['status' => $status]);
        $event->histories()->save($eventHistory);

        $eventNumber = $event->event_number;
        $eventId = $event->id;

        $masterUserId = $data['master_user_id'] ?? '';
        $masterUserName = $data['master_user_name'] ?? '';
        /**
         * 事件新增的通知
         * target: 区域负责人（区域主管 + 区域经理）
         */
        $deptService = new DeptService();
        $provinceId = intval($main['province_id'] ?? 0);
        $province = CityModel::find($provinceId);
        if (empty($province)) {
            $province = CityModel::byCityCode($provinceId)->first();
        }
        $userIds = $deptService->getLeaderIdsByProvinceId($province->id ?? 0);
        $managerIds = $deptService->getManagerIdsByProvinceId($province->id ?? 0);
        $userIds = array_unique(array_merge($userIds, $managerIds));
        NotificationRepo::multiStore($userIds, $eventId, NotificationRepo::TYPE_EVENT, self::NOTIFY_SUBMIT['title'], sprintf(self::NOTIFY_SUBMIT['content'], $eventNumber));
        if ($status == self::STATUS_UN_PROCESS) {
            /**
             * 事件分配通知
             * target: 事件负责人 + 创建人
             */
            if ($masterUserId) {
                $pushUserIds[] = $masterUserId;
                // 推送 事件新增
                $createdBy = $main['created_by'] ?? '';
                $createdType = $main['created_type'] ?? '';
                if ($createdType == self::CREATED_USER) {
                    $pushUserIds[] = $createdBy;
                }
                $pushUserIds = array_unique($pushUserIds);
                NotificationRepo::multiStore($pushUserIds, $eventId, NotificationRepo::TYPE_EVENT, self::NOTIFY_ALLOT['title'], sprintf(self::NOTIFY_ALLOT['content'], $eventNumber));
            }
        }
        // logs
        $logBody = [
            'creator' => $creatorName,
            'action' => "提交了事件，编号: {$eventNumber}"
        ];
        OperationLogRepo::createLog(OperationLogRepo::BUSINESS_TYPE_EVENT, $eventId, json_encode($logBody));
        if ($status == self::STATUS_UN_PROCESS) {
            $logBody = [
                'creator' => $actionUserName,
                'action' => "把事件 {$eventNumber} 分配给了 {$masterUserName}"
            ];
            OperationLogRepo::createLog(OperationLogRepo::BUSINESS_TYPE_EVENT, $eventId, json_encode($logBody));
        }

        // ws notify
        self::wsSend($eventId, "你有一条新事件需要处理, 编号: {$eventNumber}");
        if ($status == self::STATUS_UN_PROCESS) {
            self::wsSend($eventId, "事件已被分配, 编号: {$eventNumber}");
        }

        self::sendSms($event->id, self::SMS_SUBMIT);
        if ($status == self::STATUS_UN_PROCESS) {
            self::sendSms($event->id, self::SMS_ALLOT);
        }

        return self::fetch($event->id);
    }

    public static function sendSms($eventId, $template, $params = [])
    {
        $logger = new Logger('sms/event');
        $event = Event::find($eventId);
        $smsCode = $template['sms_code'];
        if (empty($event)) {
            $logger->info("发送失败，事件不存在, 事件ID: {$eventId}, 短信模板: {$smsCode}");
            return;
        }
        $telephone = $event->contact_telephone;
        $smsService = new SmsService($telephone);
        try {
            $smsService->sendMessage($smsCode, $params);
        } catch (\Exception $e) {
            $logger = new Logger('sms/work_order');
            $logger->error($e->getMessage());
        }
    }

    private static function requestData($id, $createdBy, $createdType)
    {
        $eventData = request()->getContent();
        $eventArr = json_decode($eventData, true);

        $params = self::params();

        $types = $params['types'];
        $type = trim($eventArr['type'] ?? '');
        if (!in_array($type, $types)) {
            throw new \Exception('事件类型错误');
        }
        $customerId = intval($eventArr['customer_id'] ?? 0);
        $customer = Customer::find($customerId);
        if (empty($customer)) {
            throw new \Exception('请选择事件所属客户');
        }
        $customerUserId = intval($eventArr['customer_user_id'] ?? 0);
        if (!$customerUserId) {
            throw new \Exception('请选择事件联系人');
        }
        $customerUser = Customer\User::find($customerUserId);
        if (empty($customerUser)) {
            throw new \Exception('联系人信息不存在');
        }

        $customerUserIds = $customer->users->pluck('id')->toArray() ?? [];
        if (!in_array($customerUserId, $customerUserIds)) {
            throw new \Exception('所选联系人不是所选客户联系人');
        }
        $contactTelephone = trim($eventArr['contact_telephone'] ?? '');

        $provinceId = intval($eventArr['province_id'] ?? 0);
        $cityId = intval($eventArr['city_id'] ?? 0);
        $countyId = intval($eventArr['county_id'] ?? 0);
        $zones = get_zones($provinceId, $cityId, $countyId);
        $address = trim($eventArr['address'] ?? '');
        $productId = intval($eventArr['product_id'] ?? 0);
        $planAt = trim($eventArr['plan_at'] ?? '');
        try {
            $planAt = Carbon::parse($planAt)->toDateString();
        } catch (\Exception $e) {
            throw new \Exception('请输入正确的计划时间');
        }

        $description = trim($eventArr['description'] ?? '');
        $eventImages = $eventArr['images'] ?? [];
        $images = [];
        foreach ($eventImages as $eventImage) {
            $images[] = [
                'image' => trim($eventImage)
            ];
        }

        $masterUserId = intval($eventArr['user_id'] ?? 0);
        $masterUserName = UserModel::find($masterUserId)->username ?? '';
        $users = [];
        if ($masterUserId) {
            $users[] = [
                'user_id' => $masterUserId,
                'is_master' => 1
            ];
        }

        if ($users) {
            $status = self::STATUS_UN_PROCESS;
        } else {
            $status = self::STATUS_UN_DISTRIBUTE;
        }
        $main = [
            'event_number' => self::generateNumber($id),
            'type' => $type,
            'customer_id' => $customerId,
            'customer_name' => $customer->name,
            'customer_user_id' => $customerUserId,
            'contact_telephone' => $contactTelephone,
            'contact_name' => $customerUser->name ?? '',
            'province_id' => $zones['province_id'],
            'province_name' => $zones['province_name'],
            'city_id' => $zones['city_id'],
            'city_name' => $zones['city_name'],
            'county_id' => $zones['county_id'],
            'county_name' => $zones['county_name'],
            'address' => $address,
            'product_id' => $productId,
            'plan_at' => $planAt,
            'description' => $description,
            'created_type' => $createdType,
            'created_by' => $createdBy,
            'status' => $status
        ];

        $result = [
            'main' => $main,
            'images' => $images,
            'users' => $users,
            'master_user_id' => $masterUserId,
            'master_user_name' => $masterUserName
        ];
        return $result;
    }

    public static function generateNumber($id)
    {
        $event = Event::find($id);
        if ($event) {
            return $event->event_number;
        }
        $number = 'CVS' . date('ymd') . rand(100000, 999999);
        $eventCount = Event::byNumber($number)->count();
        if ($eventCount) {
            return self::generateNumber($id);
        }
        return $number;
    }
}